
import java.util.BitSet;

/*
 ********************************************************************************** 
  Classe para as instruções do tipo I
 **********************************************************************************
 */
public class instrucaoI implements instrucao {
  public static final int OPCODE_BEQ = 4;
  public static final int OPCODE_BNE = 5;                         
  public static final int OPCODE_ADDI = 8;          /***********Constantes com os OPCodes de cada instrução, para refeência futura*************/
  public static final int OPCODE_LW = 35;
  public static final int OPCODE_SW= 43;
  
  private String nome;     //Nome da função, para mostrar na tela
  private registrador rS;  //Registrador rS
  private registrador rT;  //Registrador rT
  private int imediato;    //Valor do imediato em base 10
  private int opCode;      //opCode em base 10
  
  
  //Construtor, identifica a instrução e faz a inicialização de acordo
  public instrucaoI(BitSet b) {
    BitSet bitOpCode = b.get(26, 32);
    int opCodeInt = Integer.parseInt(funcoes.bitSetStr(bitOpCode, 6, true),2);
    this.opCode = opCodeInt;
    BitSet endRs = b.get(21,26);
    int numRs = Integer.parseInt(funcoes.bitSetStr(endRs, 5, true),2);
    this.rS = new registrador(numRs);
    BitSet endRt = b.get(16,21);
    int numRt = Integer.parseInt(funcoes.bitSetStr(endRt, 5, true),2);
    this.rT = new registrador(numRt);
    BitSet bitImediato = b.get(0,16);
    this.imediato = converte(funcoes.bitSetStr(bitImediato, 16, true));
    switch (opCodeInt){
      case OPCODE_BEQ:{
        this.nome = "beq";
        break;
      }
      case OPCODE_BNE:{
        this.nome = "bne";
        break;
      }
      case OPCODE_ADDI:{
        this.nome = "addi";
        break;
      }
      case OPCODE_LW:{
        this.nome = "lw";
        break;
      }
      case OPCODE_SW:{
        this.nome = "sw";
        break;
      }
    }
  }


  public int getImediato() {
    return this.imediato;
  }

  public String getNome() {
    return this.nome;
  }

  public int getOpCode() {
    return this.opCode;
  }

  public registrador getrS() {
    return this.rS;
  }

  public registrador getrT() {
    return this.rT;
  }
   
  public String toString(){
    return nome + " $" + rT.getEndereco() + ",$" + rS.getEndereco() + "," +imediato;
  }
  
  private int converte(String binario){
    String sinal = binario.substring(0,1);
    String retorno = "";
    int result;
    boolean achou = false;
    
    binario = binario.substring(1);
    
    for(int i=binario.length()-1; i>0;i--){
      if((binario.charAt(i) == '0')){
        if(achou){
          retorno = "1" + retorno;
        }else{
          retorno = "0"+ retorno;
        }
      }else{
        if(achou){
          retorno = "0" + retorno;
        }else{
          retorno = "1" + retorno;
          achou = true;
        }
      }  
    }
    result = Integer.parseInt(retorno,2);
    if(sinal.equalsIgnoreCase("1")){
      result *= -1;
    }
    return result;
  }  
}
